/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.core.ui.dialogs;


import java.util.Iterator;

import org.eclipse.gef.commands.CommandStack;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.EncapsulatedClassifier;
import org.eclipse.uml2.uml.Port;
import org.eclipse.uml2.uml.Reception;
import org.eclipse.uml2.uml.Signal;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.commands.UMLElementCreateCommand;
import com.cea.papyrus.core.commands.UMLElementDeleteCommand;
import com.cea.papyrus.core.editor.CommandStackUtils;

/**
 * Dialog to select a Signal from the Reception list of an active Class.
 * 
 * @author David Servat
 * @since 5. apr. 2007
 */
public class ActiveClassSignalTreeSelectionDialog extends Dialog{

	/**
	 * The Class for which we want to show a list of signals.
	 */
	protected org.eclipse.uml2.uml.Class clazz;

	/**
	 * Chosen signal.
	 */
	protected Signal signal;

	/**
	 * The selection tree.
	 */
	protected Tree tree;

	/**
	 * Button to create new reception
	 */
	protected Button newButton;

	/**
	 * Label for description
	 */
	protected Label label;

	/**
	 * Constructor with parent shell and Class.
	 * 
	 * @param parent the Shell.
	 * @param clazz the Class.
	 */
	public ActiveClassSignalTreeSelectionDialog(Shell parent, org.eclipse.uml2.uml.Class clazz){
		super(parent);
		this.clazz = clazz;
		// add the resize ability to the window
		setShellStyle(SWT.RESIZE | super.getShellStyle());
	}

	/**
	 * Creates the dialog area.
	 * 
	 * @param parent composite.
	 * 
	 * @return control Control.
	 */
	protected Control createDialogArea(Composite parent){
		Composite composite = (Composite)super.createDialogArea(parent);

		label = new Label(composite, SWT.NONE);
		label.setText("Select an existing Signal reception or create a new one:");
		label.setLayoutData(new GridData());

		newButton = new Button(composite, SWT.NONE);
		newButton.setText("New Signal reception");
		newButton.setToolTipText("This button will let you create a Reception on an existing Signal");
		newButton.setLayoutData(new GridData(200, 25));

		tree = new Tree(composite, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL);

		final org.eclipse.uml2.uml.Class currentClass = clazz;

		//build subtree for operations contained in the BehavioredClassifier
		TreeItem item = new TreeItem(tree, SWT.NONE);
		item.setText("Signal receptions declared on the classifier:");
		item.setImage(PapyrusPlugin.UML_LABEL_PROVIDER.getImage(currentClass));
		buildTreeList(item, currentClass);

		final TreeItem classItem = item;
		final Composite par = parent;
		
		//build subtree for operations contained in all behavioral ports
		if(clazz instanceof EncapsulatedClassifier){
			Iterator iter = ((EncapsulatedClassifier)clazz).getOwnedPorts().iterator();
			while(iter.hasNext()){
				Port port = (Port)iter.next();
				if(port.isBehavior()){
					item = new TreeItem(tree, SWT.NONE);
					item.setText("Signal receptions declared on the behavioral port: "+port.getName());
					item.setImage(PapyrusPlugin.UML_LABEL_PROVIDER.getImage(port));
					buildTreeList(item, (Classifier)port.getType());
				}
			}
		}

		tree.setLayoutData(new GridData(550, 300));

		tree.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e){
				TreeItem[] selection = tree.getSelection();
				if(selection[0].getData() instanceof Signal){
					signal = (Signal)selection[0].getData();
				}
			}

			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});
		
		newButton.addMouseListener(new MouseListener(){
			public void mouseDoubleClick(MouseEvent e) {
			}

			public void mouseDown(MouseEvent e) {
			}

			public void mouseUp(MouseEvent e) {

				// creation command
				final UMLElementCreateCommand command = new UMLElementCreateCommand(Reception.class, currentClass);

				CommandStack commandStack = CommandStackUtils.getCommandStack();
				if(commandStack!= null) {
					commandStack.execute(command);
				}

				Reception newReception = (Reception)command.getElement();
				
				ReceptionSignalTreeSelectionDialog dialog = new ReceptionSignalTreeSelectionDialog(par.getShell(), newReception);
				int result = dialog.open();
				
				//check the result
				if(result == IDialogConstants.OK_ID){
					signal = dialog.getResult();
					if(signal != null){
						newReception.setSignal(signal);
						
						TreeItem signalItem = new TreeItem(classItem, SWT.SINGLE);
						signalItem.setText(signal.getQualifiedName());
						signalItem.setData(signal);
						signalItem.setImage(PapyrusPlugin.UML_LABEL_PROVIDER.getImage(signal));
		
						tree.setSelection(signalItem);
					}
					else{
						final UMLElementDeleteCommand delCommand = new UMLElementDeleteCommand(newReception, currentClass);

						commandStack = CommandStackUtils.getCommandStack();
						if(commandStack!= null){
							commandStack.execute(command);
						}
					}
				}
				else{
					final UMLElementDeleteCommand delCommand = new UMLElementDeleteCommand(newReception, currentClass);

					commandStack = CommandStackUtils.getCommandStack();
					if(commandStack!= null){
						commandStack.execute(delCommand);
					}
				}
					
			}

		});

		return composite;
	}

	/**
	 * This method builds a Reception tree widget for each Classifier
	 * 
	 * @param classifier Classifier 
	 * @param item TreeItem 
	 */
	protected void buildTreeList(TreeItem classifierTree, Classifier classifier){
		Iterator iter = classifier.allFeatures().iterator();
		while(iter.hasNext()){
			Element currentElement = (Element)iter.next();
			if(currentElement instanceof Reception){
				Signal currentSignal = ((Reception)currentElement).getSignal();
				if(currentSignal != null){
					TreeItem item = new TreeItem(classifierTree, SWT.NONE);
					item.setText(currentSignal.getQualifiedName());
					item.setData(currentSignal);
					item.setImage(PapyrusPlugin.UML_LABEL_PROVIDER.getImage(currentSignal));
				}
			}
		}
	}


	/**
	 * Returns the associated Signal.
	 * 
	 * @return signal Signal
	 */
	public Signal getResult(){
		return signal;
	}
	
	/* (non-Javadoc)
	 * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
	 */
	@Override
	protected void configureShell(Shell shell) {
		super.configureShell(shell);
		shell.setText(clazz.getName()+": Signal Selection");
	}

}
